/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.saga.lib.asyncserver;

import java.io.IOException;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;

/**
 *
 * This is injected by Guice and should hold no state.
 * 
 * @author summers
 */
public class ConnectionCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Server> {

    private static final Logger LOG = Logger.getLogger(ConnectionCompletionHandler.class.getName());

    private Class<? extends ConnectionState> defaultClazz;
    
    private ConnectionStateFactory connectionStateFactory;
    

    public ConnectionCompletionHandler(@Named("DefaultClass") Class<? extends ConnectionState> defaultClazz) {
        this.defaultClazz = defaultClazz;
        this.connectionStateFactory = new DefaultConnectionStateFactory();
    }
    
    @Inject
    public ConnectionCompletionHandler( @Named("DefaultClass")Class defaultClazz, ConnectionStateFactory connectionStateFactory) {
        this.defaultClazz = (Class<? extends ConnectionState>)defaultClazz;
        this.connectionStateFactory = connectionStateFactory;
    }
    
    
    
    @Override
    public void completed(final AsynchronousSocketChannel channel, Server attachment) {
       
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                double id = Math.random();
                
                ConnectionState state = connectionStateFactory.get(defaultClazz, channel);
                state.setChannel(channel);

                while (state != null) {
                    
                    ConnectionState newState = state.run();
                    
                    if (newState != state) {//Yes I am checking to make sure they are the same instance
                        connectionStateFactory.checkin(state);
                    }
                    state = newState;
                    
                }
                LOG.log(Level.INFO, "Finished {0}", id);
                try {
                    channel.close();
                } catch (IOException ex) {
                    LOG.log(Level.SEVERE, "close failed", ex);
                }
            }
        }).start();
        attachment.accept();

    }

    @Override
    public void failed(Throwable exc, Server attachment) {
        LOG.log(Level.SEVERE, "Failed connection", exc);
    }
}
